const { Controller } = require('egg');
const SortWord = require('sort-word');

class friendController extends Controller {
  async addFriend() {
    // 添加好友
    const { ctx, app } = this;
    // 1. 参数验证
    ctx.validate({
      friend_id: {
        type: 'int',
        required: true,
        desc: '好友id'
      },
      username: {
        type: 'string',
        required: true,
        desc: '用户名'
      },
      lookme: {
        type: 'int',
        required: true,
        range: {
          in: [0, 1]
        }
      },
      lookhim: {
        type: 'int',
        required: true,
        range: {
          in: [0, 1]
        }
      }
    });
    // 2. 获取参数
    const { friend_id, username, lookme, lookhim } = ctx.request.body;
    // 3. 查询用户是否存在
    const lieUser = await app.model.User.findOne({
      where: {
        id: friend_id,
        status: 1
      }
    });
    if (!lieUser) {
      ctx.throw(400, '用户不存在');
    }
    // 4. 是否添加的是自己
    const id = ctx.authUser.id;
    if (friend_id === id) {
      ctx.throw(400, '不能添加自己哦!');
    }
    // 5. 查询是否已经发起过好友申请了
    const friend = await app.model.Apply.findOne({
      where: {
        user_id: id,
        friend_id,
        status: ['pending', 'agree']
      }
    });
    if (friend) {
      ctx.throw(400, '已经添加过了哦,请等待对方处理');
    }
    // 6. 添加好友申请
    const apply = await app.model.Apply.create({
      user_id: id,
      friend_id,
      nickname: username,
      lookme,
      lookhim
    });
    if (!apply) {
      ctx.fail('添加失败');
    }
    // 通知对方
    const message = {
      id: new Date().getTime(), // 唯一id，后端生成唯一id
      from_avatar: ctx.authUser.avatar, // 发送者头像
      from_name: ctx.authUser.username, // 发送者昵称
      from_id: id, // 发送者id
      to_id: friend_id, // 接收人/群 id
      to_name: lieUser.username, // 接收人/群 名称
      to_avatar: lieUser.avatar, // 接收人/群 头像
      chat_type: 'user', // 接收类型
      type: 'user', // 消息类型
      data: `${ctx.authUser.username}请求添加您为好友!`, // 消息内容
      options: {}, // 其他参数
      create_time: new Date().getTime(), // 创建时间
      isremove: 0 // 是否撤回
    };
    ctx.sendMessage(friend_id, message, 'newFriend');
    // 返回
    ctx.success('添加成功');
  }
  async deleteFriend() {
    // 删除好友
    const { ctx, app } = this;
    // 1. 参数验证获取
    const id = ctx.authUser.id;
    const f_id = ctx.params.f_id;
    // 2 开始事务 操作数据库
    let transaction = null;
    try {
      transaction = await app.model.transaction(); // 开启事务
      await app.model.Friend.destroy(
        {
          // 将对方从我的好友列表中删除
          where: {
            user_id: id,
            friend_id: f_id
          }
        },
        { transaction }
      );
      await app.model.Friend.destroy(
        {
          // 将我从对方的好友列表中删除
          where: {
            user_id: f_id,
            friend_id: id
          }
        },
        { transaction }
      );
      await transaction.commit(); // 上面是任务成功 提交事务
      // 4. 返回结果
      ctx.success('处理成功');
    } catch (err) {
      await transaction.rollback();
      ctx.throw(500, '操作失败');
    }
  }
  async list() {
    // 获得好友申请列表
    const { ctx, app } = this;
    // 1. 获取参数信息和用户id
    const id = ctx.authUser.id;
    const page = ctx.query.page || 1;
    // 2. 查询用户申请列表关联user并统计总条数
    const applyList = await app.model.Apply.findAndCountAll({
      where: {
        friend_id: id,
        status: 'pending'
      },
      include: [
        {
          model: app.model.User,
          attributes: ['id', 'username', 'avatar', 'area', 'created_at']
        }
      ],
      offset: (page - 1) * 10,
      limit: 10,
      order: [['created_at', 'DESC']]
    });
    // 4. 返回结果
    ctx.success(applyList);
  }
  async handle() {
    // 处理好友申请
    const { ctx, app } = this;
    // 1. 参数验证和参数获取
    ctx.validate({
      username: {
        type: 'string',
        required: true,
        desc: '用户名'
      },
      friend_id: {
        type: 'int',
        required: true,
        desc: '好友id'
      },
      status: {
        type: 'string',
        required: true,
        range: {
          in: ['agree', 'refuse']
        },
        desc: '处理状态'
      },
      lookme: {
        type: 'int',
        required: true,
        range: {
          in: [0, 1]
        },
        describe: '是否查看我的动态'
      },
      lookhim: {
        type: 'int',
        required: true,
        range: {
          in: [0, 1]
        },
        describe: '是否查看我的动态'
      }
    });
    const { username, status, lookme, lookhim, friend_id } = ctx.request.body;
    const id = ctx.authUser.id;
    // 2. 查询该申请是否存在
    const apply = await app.model.Apply.findOne({
      where: {
        friend_id: id,
        user_id: friend_id,
        status: 'pending'
      }
    });
    if (!apply) {
      ctx.throw(400, '申请不存在');
    }
    // 3. 更新申请状态
    let transaction = null;
    try {
      transaction = await app.model.transaction(); // 开启事务
      await apply.update({
        // 更新申请状态
        status
      });
      if (status === 'agree') {
        // 同意申请
        await app.model.Friend.create(
          {
            // 将我加入到对方的好友列表
            friend_id: id,
            user_id: friend_id,
            nickname: apply.nickname,
            lookme: apply.lookme,
            lookhim: apply.lookhim
          },
          { transaction }
        );
        await app.model.Friend.create(
          {
            // 将对方加入到我的好友列表
            friend_id,
            user_id: id,
            nickname: username,
            lookhim,
            lookme
          },
          { transaction }
        );
        await transaction.commit(); // 上面是任务成功 提交事务
        // 4. 返回结果
        ctx.success('处理成功');
      }
    } catch (err) {
      await transaction.rollback();
      ctx.throw(500, '操作失败');
    }
  }
  async friendList() {
    // 获得朋友列表
    // 1. 获取参数
    const { app, ctx } = this;
    const { id } = ctx.authUser;
    // 2. 查询朋友列表并计数
    const friends = await app.model.Friend.findAndCountAll({
      where: {
        user_id: id
      },
      include: [
        {
          model: app.model.User,
          as: 'friendInfo',
          attributes: ['id', 'username', 'nickname', 'avatar']
        }
      ]
    });
    // 3. 数据整理
    const res = friends.rows.map((item) => {
      let name = item.friendInfo.nickname
        ? item.friendInfo.nickname
        : item.friendInfo.username;
      if (item.nickname) {
        name = item.nickname;
      }
      return {
        id: item.id,
        user_id: item.friendInfo.id,
        nickname: name,
        username: item.friendInfo.username,
        avatar: item.friendInfo.avatar
      };
    });
    // 排序
    if (res.length > 0) {
      friends.rows = new SortWord(res, 'nickname');
    }
    // console.log(111);
    // 4. 返回结果
    ctx.success(friends);
  }
  async friendUser() {
    // 查看好友信息 user表
    // 1. 获得参数以及解构
    const { app, ctx } = this;
    const f_id = ctx.query.id;
    // 2. 获得朋友信息
    const info = await app.model.User.findOne({
      where: {
        id: f_id
      },
      attributes: {
        exclude: ['password']
      },
      include: {
        model: app.model.Friend,
        as: 'bfriends',
        where: {
          user_id: ctx.authUser.id
        }
      }
    });
    if (!info) {
      ctx.throw(400, '你们可能不存在好友关系或对方不存在');
    }
    ctx.success(info);
  }
  async friendInfo() {
    // 查看好友信息 friend
    const { ctx, app } = this;
    ctx.validate({
      id: {
        type: 'int',
        required: true,
        desc: '好友表的id'
      },
      friend_id: {
        type: 'int',
        required: true,
        desc: '好友id'
      }
    });
    const { id, friend_id } = ctx.request.query;
    const friend = await app.model.Friend.findOne({
      where: {
        id,
        friend_id
      }
    });
    if (!friend) {
      ctx.throw(400, '好友不存在');
    }
    ctx.success(friend);
  }
  async setremarkTag() {
    // 给好友设置备注和标签
    // 1. 参数整理和格式验证
    const { ctx, app } = this;
    const { tag, nickname } = ctx.request.body;
    const id = ctx.authUser.id;
    const friend_id = ctx.params.f_id;
    ctx.validate({
      tag: {
        type: 'string',
        required: false,
        desc: '用户标签'
      },
      nickname: {
        type: 'string',
        required: true,
        desc: '用户备注'
      }
    });
    // 2. 验证此好友是否存在
    const friend = await app.model.Friend.findOne({
      where: {
        user_id: id,
        friend_id,
        isblack: 0
      }
    });
    if (!friend) {
      ctx.throw(400, '此好友不存在');
    }
    // 3. 修改好友的备注
    friend.nickname = nickname;
    await friend.save();
    // 4. 获得来用户的标签并整理传递过来的标签格式
    if (tag.length > 0) {
      // 新的标签存在才进行
      const oldTagDB = await app.model.Tag.findAll({
        where: {
          user_id: id
        }
      });
      const oldTagArr = oldTagDB.map((item) => item.name);
      const newTagArr = tag.split(',');
      // 选出新标签中旧标签中没有的
      const newTag = newTagArr.filter((item) => !oldTagArr.includes(item));
      if (newTag.length > 0) {
        // 将没有的标签存进用户标签中
        const data = newTag.map((item) => {
          return {
            name: item,
            user_id: id
          };
        });
        const saveTag = await app.model.Tag.bulkCreate(data);
        if (!saveTag) {
          ctx.throw(500, '标签保存失败');
        }
        // 找到新标签的id
        const newTagDB = await app.model.Tag.findAll({
          where: {
            user_id: id,
            name: newTagArr
          }
        });
        if (!newTagDB) {
          ctx.throw(500, '标签查找失败');
        }
        // 获得新旧的标签id
        const newTagId = newTagDB.map((item) => item.id);
        const oldTagId = oldTagDB.map((item) => item.id);

        const addTagsIds = newTagId.filter((id) => !oldTagId.includes(id));
        const delTagsIds = oldTagId.filter((id) => !newTagId.includes(id));

        if (addTagsIds.length > 0) {
          // 添加关联关系
          const addTags = addTagsIds.map((tag_id) => {
            return {
              tag_id,
              friend_id: friend.id
            };
          });
          console.log(addTags);
          await app.model.FriendTag.bulkCreate(addTags);
        }
        if (delTagsIds.length > 0) {
          // 删除关联关系
          app.model.FriendTag.destroy({
            where: {
              tag_id: delTagsIds,
              friend_id: friend.id
            }
          });
        }
      }
    }
    ctx.success('操作成功');
  }
  async editFriendNote() {
    // 修改好友备注
    // 1. 参数整理和格式验证
    const { ctx, app } = this;
    const id = ctx.authUser.id;
    const friend_id = ctx.params.f_id;
    ctx.validate({
      nickname: {
        type: 'string',
        required: false,
        desc: '好友备注'
      }
    });
    const { nickname } = ctx.request.body;
    // 2. 验证此好友是否存在
    const friend = await app.model.Friend.findOne({
      where: {
        user_id: id,
        friend_id,
        isblack: 0
      }
    });
    if (!friend) {
      ctx.throw(400, '此好友不存在');
    }
    // 3. 修改好友的备注
    friend.nickname = nickname;
    await friend.save();
    ctx.success('操作成功');
  }
  async setStar() {
    // 设置或者取消星标好友
    // 1. 参数整理和格式验证
    const { ctx, app } = this;
    const { star } = ctx.request.body;
    const id = ctx.authUser.id;
    const friend_id = ctx.params.f_id;
    ctx.validate({
      star: {
        type: 'boolean',
        required: true,
        desc: '是否星标好友'
      }
    });
    // 2. 验证此好友是否存在
    const friend = await app.model.Friend.findOne({
      where: {
        user_id: id,
        friend_id
      }
    });
    if (!friend) {
      ctx.throw(400, '此好友不存在');
    }
    friend.star = star;
    await friend.save();
    ctx.success('操作成功');
  }
  async setBlock() {
    // 设置或者取消拉黑
    // 1. 参数整理和格式验证
    const { ctx, app } = this;
    const { block } = ctx.request.body;
    const id = ctx.authUser.id;
    const friend_id = ctx.params.f_id;
    ctx.validate({
      block: {
        type: 'boolean',
        required: true,
        desc: '是否拉黑'
      }
    });
    // 2. 验证此好友是否存在
    const friend = await app.model.Friend.findOne({
      where: {
        user_id: id,
        friend_id
      }
    });
    if (!friend) {
      ctx.throw(400, '此好友不存在');
    }
    friend.isblack = block;
    await friend.save();
    ctx.success('操作成功');
  }
  async setLook() {
    // 设置boyi圈权限
    // 1. 参数整理和格式验证
    const { ctx, app } = this;
    const { lookme, lookhim } = ctx.request.body;
    const id = ctx.authUser.id;
    const friend_id = ctx.params.f_id;
    ctx.validate({
      lookme: {
        type: 'boolean',
        required: true,
        desc: '是否允许查看我的朋友圈'
      },
      lookhim: {
        type: 'boolean',
        required: true,
        desc: '是否允许查看他的朋友圈'
      }
    });
    // 2. 验证此好友是否存在
    const friend = await app.model.Friend.findOne({
      where: {
        user_id: id,
        friend_id
      }
    });
    if (!friend) {
      ctx.throw(400, '此好友不存在');
    }
    friend.lookme = lookme;
    friend.lookhim = lookhim;
    await friend.save();
    ctx.success('操作成功');
  }
}

module.exports = friendController;
